home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 23 / CU Amiga - Super CD-ROM 23 (June 1998).iso / CUCD / Graphics / STIMP_noise / source / include / STIMP / pnm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-02-14  |  11.0 KB  |  410 lines

  1.  
  2. // PNM: declarations and routines
  3. // Version 2.02, 11.Feb.98
  4. // (c) 1997/98 by Stefan Diener
  5.  
  6. #ifndef STIMP_PNM_INC
  7. #define STIMP_PNM_INC
  8.  
  9. // We do not need the pseudo modes !
  10. #ifndef NO_PSEUDO_PGM_MODE
  11. #define NO_PSEUDO_PGM_MODE
  12. #endif
  13.  
  14. #ifndef NO_PSEUDO_PPM_MODE
  15. #define NO_PSEUDO_PPM_MODE
  16. #endif
  17.  
  18. #include <STIMP/pbm.c>
  19. #include <STIMP/pgm.c>
  20. #include <STIMP/ppm.c>
  21.  
  22. struct PNM_Info
  23. {
  24.   char type;
  25.   unsigned int height;
  26.   unsigned int width;
  27.   unsigned int maxval;
  28.   union
  29.   {
  30.     unsigned char *gray;
  31.     struct
  32.     {
  33.       unsigned char *red;
  34.       unsigned char *green;
  35.       unsigned char *blue;
  36.     } RGB;
  37.   } DATEN;
  38. };
  39.  
  40. #define DATA        DATEN.gray
  41. #define redDATA    DATEN.RGB.red
  42. #define greenDATA    DATEN.RGB.green
  43. #define blueDATA    DATEN.RGB.blue
  44.  
  45. #define TYPE_PNM TYPE_PBM+TYPE_PGM+TYPE_PPM
  46.  
  47. int ReadPNMFile(char *name, int mask, struct PNM_Info *info)
  48. // read a PNM-file
  49. {
  50.   FILE *datei;
  51.   char tempo[5];
  52.   int type=0, zeile;
  53.   long int i, j, k, elemente, gesamt, anzahl;
  54.   unsigned char *srcR, *srcG, *srcB, *src;
  55.   unsigned char *Puffer, *zeiger, zwisch;
  56.  
  57.   if (strcmp("-",name)==0) datei=stdin;   // use stdin
  58.   else
  59.   {
  60.     // really open a file
  61.     datei=fopen(name,"rb");
  62.     if (datei==0)
  63.     {
  64.       PrintMessage("File %s not found !", name);
  65.       return 1;
  66.     }
  67.   }
  68.  
  69.   // set buffer size
  70.   setvbuf(datei,0,_IOFBF,1000);
  71.  
  72.   // check type
  73.   fgets(tempo, 4, datei);
  74.   correct(tempo);
  75.   if (strcmp(tempo,"P4")==0) type=TYPE_PBM;
  76.   if (strcmp(tempo,"P5")==0) type=TYPE_PGM;
  77.   if (strcmp(tempo,"P6")==0) type=TYPE_PPM;
  78.  
  79.   if (mask & type)
  80.   {
  81.     info->type=type;
  82.  
  83.     // read dimensions
  84.     // skip comments !!!
  85.     ReadComment(datei);
  86.     fscanf(datei,"%i %i\n",&info->width,&info->height);
  87.     gesamt=info->width*info->height;
  88.  
  89.     // read maxval if not a PBM image
  90.     // skip comments !!!
  91.     if (type!=TYPE_PBM)
  92.     {
  93.       ReadComment(datei);
  94.       fscanf(datei,"%i\n",&info->maxval);
  95.     }
  96.  
  97.     switch (type)
  98.     {
  99.       case TYPE_PBM :   // PBM routine !!!!!!!!!!
  100.         // print it on the screen
  101.         PrintMessage("Reading %s (PBM, %ix%i)", name, info->width, info->height);
  102.  
  103.         // allocate memory for the picture
  104.         info->DATA=NULL;
  105.         info->DATA=(unsigned char *) malloc(gesamt*sizeof(unsigned char));
  106.         if (info->DATA==NULL)
  107.         {
  108.           PrintMessage("No memory for the picture data left !");
  109.           if (strcmp("-",name)!=0) fclose(datei);
  110.           return 1;
  111.         }
  112.  
  113.         // need an empty picture
  114.         src=info->DATA;
  115.         for (i=0;i<gesamt;i++) *src++=0;
  116.  
  117.         // initialize help variables
  118.         src=info->DATA;
  119.         zeile=info->width;
  120.         if (zeile%8) zeile=zeile-(zeile%8)+8;
  121.         zeile=zeile/8;
  122.  
  123.         // read picture data
  124.         for (i=0; i<info->height; i++)
  125.         {
  126.           for (k=0; k<zeile; k++)
  127.           {
  128.             j=fgetc(datei);
  129.             if (j==EOF)
  130.             {
  131.               PrintMessage("Unexpected end of file !");
  132.               i=info->height;
  133.               k=zeile;
  134.             }
  135.             else
  136.             {
  137.               zwisch=(unsigned char) j;
  138.               for (j=7; j>=0; j--)
  139.               {
  140.                 // Bit==0 => white, Bit==1 => black
  141.                 if (k*8+j<info->width) src[i*info->width+k*8+j]=((zwisch%2)?0:255);
  142.                 zwisch=zwisch>>1;
  143.               }
  144.             }
  145.           }
  146.         }
  147.  
  148.         // init maxval, even of not really needed
  149.         info->maxval=255;
  150.         break;
  151.  
  152.        case TYPE_PGM :   // PGM routine !!!!!!!!!!
  153.         // print it on the screen
  154.         PrintMessage("Reading %s (PGM, %ix%i)", name, info->width, info->height);
  155.  
  156.         // allocate memory for picture data
  157.         info->DATA=NULL;
  158.         info->DATA=(unsigned char *) malloc(gesamt*sizeof(unsigned char));
  159.         if (info->DATA==NULL)
  160.         {
  161.           PrintMessage("No memory for the picture data left !");
  162.           if (strcmp("-",name)!=0) fclose(datei);
  163.           return 1;
  164.         }
  165.  
  166.         // need an empty picture
  167.         src=info->DATA;
  168.         for (i=0; i<gesamt; i++) *src++=0;
  169.  
  170.         // read picture data
  171.         i=fread((void *) info->DATA, sizeof(unsigned char), gesamt, datei);
  172.         if (i!=gesamt) PrintMessage("Error while reading the file !");
  173.         break;
  174.  
  175.       case TYPE_PPM :   // PPM routine !!!!!!!!!!
  176.         // print it on the screen
  177.         PrintMessage("Reading %s (PPM, %ix%i)", name, info->width, info->height);
  178.  
  179.         // allocate memory for the read buffer
  180.         Puffer=NULL;
  181.         Puffer=(unsigned char *) malloc(PPM_PUFFER_SIZE*sizeof(unsigned char));
  182.         if (Puffer==NULL)
  183.         {
  184.           PrintMessage("No memory for the read buffer left !");
  185.           if (strcmp("-",name)!=0) fclose(datei);
  186.           return 1;
  187.         }
  188.  
  189.         // allocate memory for red picture data
  190.         info->redDATA=NULL;
  191.         info->redDATA=(unsigned char *) malloc(gesamt*sizeof(unsigned char));
  192.         if (info->redDATA==NULL)
  193.         {
  194.           PrintMessage("No memory for red picture data left !");
  195.           free((void *) Puffer);
  196.           if (strcmp("-",name)!=0) fclose(datei);
  197.           return 1;
  198.         }
  199.  
  200.         // allocate memory for green picture data
  201.         info->greenDATA=NULL;
  202.         info->greenDATA=(unsigned char *) malloc(gesamt*sizeof(unsigned char));
  203.         if (info->greenDATA==NULL)
  204.         {
  205.           PrintMessage("No memory for green picture data left !");
  206.           free((void *) Puffer);
  207.           free((void *) info->redDATA);
  208.           if (strcmp("-",name)!=0) fclose(datei);
  209.           return 1;
  210.         }
  211.  
  212.         // allocate memory for blue picture data
  213.         info->blueDATA=NULL;
  214.         info->blueDATA=(unsigned char *) malloc(gesamt*sizeof(unsigned char));
  215.         if (info->blueDATA==NULL)
  216.         {
  217.           PrintMessage("No memory for blue picture data left !");
  218.           if (strcmp("-",name)!=0) fclose(datei);
  219.           free((void *) Puffer);
  220.           free((void *) info->redDATA);
  221.           free((void *) info->greenDATA);
  222.           return 1;
  223.         }
  224.  
  225.         // need an empty picture
  226.         srcR=info->redDATA;
  227.         srcG=info->greenDATA;
  228.         srcB=info->blueDATA;
  229.         for (i=0; i<gesamt; i++)
  230.         {
  231.            *srcR++=0;
  232.            *srcG++=0;
  233.            *srcB++=0;
  234.         }
  235.  
  236.         // get pointers
  237.         srcR=info->redDATA;
  238.         srcG=info->greenDATA;
  239.         srcB=info->blueDATA;
  240.  
  241.         // read picture data
  242.         i=0;
  243.         elemente=PPM_PUFFER_SIZE/3;
  244.         while (i<gesamt)
  245.         {
  246.           anzahl=gesamt-i;
  247.           if (anzahl>elemente) anzahl=elemente;
  248.           j=fread((void *) Puffer, sizeof(unsigned char), anzahl*3, datei);
  249.           if (j!=anzahl*3)
  250.           {
  251.             i=gesamt;
  252.             PrintMessage("Error while reading the file !");
  253.           }
  254.           else
  255.           {
  256.             i+=anzahl;
  257.             zeiger=Puffer;
  258.             for (j=0; j<anzahl; j++)
  259.             {
  260.               *srcR++=*zeiger++;
  261.               *srcG++=*zeiger++;
  262.               *srcB++=*zeiger++;
  263.             }
  264.           }
  265.         }
  266.  
  267.         // free buffer memory
  268.         free((void *) Puffer);
  269.         break;
  270.     }
  271.  
  272.     // close file
  273.     if (strcmp("-",name)!=0) fclose(datei);
  274.   }
  275.   else
  276.   {
  277.     if (strcmp("-",name)!=0) fclose(datei);   // really close something
  278.     PrintMessage("Wrong file type: %s !",name);
  279.     return 1;
  280.   }
  281.  
  282.   // ok
  283.   return 0;
  284. }
  285.  
  286. int WritePNMFile(char *name, struct PNM_Info *info)
  287. // write a PNM-file
  288. {
  289.   int error=0;
  290.   struct PBM_Info infoB;
  291.   struct PGM_Info infoG;
  292.   struct PPM_Info infoP;
  293.  
  294.   switch (info->type)
  295.   {
  296.     case TYPE_PBM: infoB.width=info->width;
  297.                               infoB.height=info->height;
  298.                               infoB.Data=info->DATA;
  299.                               error=WritePBMFile(name, &infoB);
  300.                               break;
  301.  
  302.     case TYPE_PGM: infoG.width=info->width;
  303.                               infoG.height=info->height;
  304.                               infoG.maxval=info->maxval;
  305.                               infoG.Data=info->DATA;
  306.                               error=WritePGMFile(name, &infoG);
  307.                               break;
  308.  
  309.     case TYPE_PPM: infoP.width=info->width;
  310.                               infoP.height=info->height;
  311.                               infoP.maxval=info->maxval;
  312.                               infoP.redData=info->redDATA;
  313.                               infoP.greenData=info->greenDATA;
  314.                               infoP.blueData=info->blueDATA;
  315.                               error=WritePPMFile(name, &infoP);
  316.                               break;
  317.   }
  318.  
  319.   return error;
  320. }
  321.  
  322. int CreatePNMArray(int y, int x, int typ, struct PNM_Info *info)
  323. // allocate memory for a PNM-picture
  324. {
  325.   int error=0;
  326.   struct PBM_Info infoB;
  327.   struct PGM_Info infoG;
  328.   struct PPM_Info infoP;
  329.  
  330.   switch (typ)
  331.   {
  332.     case TYPE_PBM: error=CreatePBMArray(y, x, &infoB);
  333.                               break;
  334.  
  335.     case TYPE_PGM: error=CreatePGMArray(y, x, &infoG);
  336.                               break;
  337.  
  338.     case TYPE_PPM: error=CreatePPMArray(y, x, &infoP);
  339.                               break;
  340.  
  341.     default: error=1;
  342.                  break;
  343.   }
  344.  
  345.   if (error==0)
  346.   {
  347.     info->type=typ;
  348.  
  349.     switch (typ)
  350.     {
  351.       case TYPE_PBM: info->height=infoB.height;
  352.                                 info->width=infoB.width;
  353.                                 info->maxval=255;
  354.                                 info->DATA=infoB.Data;
  355.                                 break;
  356.  
  357.       case TYPE_PGM: info->height=infoG.height;
  358.                                 info->width=infoG.width;
  359.                                 info->maxval=infoG.maxval;
  360.                                 info->DATA=infoG.Data;
  361.                                 break;
  362.  
  363.       case TYPE_PPM: info->height=infoP.height;
  364.                                 info->width=infoP.width;
  365.                                 info->maxval=infoP.maxval;
  366.                                 info->redDATA=infoP.redData;
  367.                                 info->greenDATA=infoP.greenData;
  368.                                 info->blueDATA=infoP.blueData;
  369.                                 break;
  370.     }
  371.   }
  372.  
  373.   return error;
  374. }
  375.  
  376. void FreePNMArray(struct PNM_Info *info)
  377. // free the memory of a PNM-picture
  378. {
  379.   struct PBM_Info infoB;
  380.   struct PGM_Info infoG;
  381.   struct PPM_Info infoP;
  382.  
  383.   switch (info->type)
  384.   {
  385.     case TYPE_PBM: infoB.width=info->width;
  386.                               infoB.height=info->height;
  387.                               infoB.Data=info->DATA;
  388.                               FreePBMArray(&infoB);
  389.                               break;
  390.  
  391.     case TYPE_PGM: infoG.width=info->width;
  392.                               infoG.height=info->height;
  393.                               infoG.maxval=info->maxval;
  394.                               infoG.Data=info->DATA;
  395.                               FreePGMArray(&infoG);
  396.                               break;
  397.  
  398.     case TYPE_PPM: infoP.width=info->width;
  399.                               infoP.height=info->height;
  400.                               infoP.maxval=info->maxval;
  401.                               infoP.redData=info->redDATA;
  402.                               infoP.greenData=info->greenDATA;
  403.                               infoP.blueData=info->blueDATA;
  404.                               FreePPMArray(&infoP);
  405.                               break;
  406.   }
  407. }
  408.  
  409. #endif
  410.